/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package linkedlist;

import java.util.Scanner;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author Islam Hamdi
 */
public class Polynomial {
        private static  MyLinkedListS<PolTerm> A=new MyLinkedListS<PolTerm>();
        private static MyLinkedListS<PolTerm> B=new MyLinkedListS<PolTerm>();
        private static MyLinkedListS<PolTerm> C=new MyLinkedListS<PolTerm>();
        private static MyLinkedListS<PolTerm> R=new MyLinkedListS<PolTerm>();


        private static int takeAction(){
            Scanner sc=new Scanner(System.in);
            String line="";
            Pattern pattern=Pattern.compile("[1-7]{1,1}\\z");
            Matcher matcher;
            do{
                getInstructions();
                line=sc.nextLine();
                matcher=pattern.matcher(line);
            }while(!matcher.find());

            return Integer.parseInt(line);
        }
        
        private static void request(int n){
            Scanner sc=new Scanner(System.in);
            switch(n){
                case 1:
                    String temp="";
                    do{
                        System.out.println("Insert the variable name: A, B or C");
                        temp=sc.nextLine();
                        }while(!temp.equals("A")&&!temp.equals("B")&&!temp.equals("C"));
                        insertPolynom(temp);
                    break;
                case 2:
                    String input="";
                   do{
                    System.out.println("Insert the variable name: A, B, C or R");
                    input=sc.nextLine();
                   }while(!input.equals("A")&&!input.equals("B")&&!input.equals("C"));
                    printPol(input);
                    break;
                case 3:
                    int counter=0;
                    String list="";
                      do{
                          do{
                                System.out.println("Insert First Operand Variable name:: A, B or C");
                                temp=sc.nextLine();
                           }while(!temp.equals("A")&&!temp.equals("B")&&!temp.equals("C"));
                           if(temp.equals("A")){
                               if(A.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                   list="A";
                               }
                           }else if(temp.equals("B")){
                               if(B.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                  list="B";
                               }
                           }else {
                               if(C.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                   list="C";
                               }
                           }
                           counter++;
                            do{
                                System.out.println("Insert Second Operand Variable name:: A, B or C");
                                temp=sc.nextLine();
                            }while(!temp.equals("A")&&!temp.equals("B")&&!temp.equals("C"));
                           if(temp.equals("A")){
                               if(A.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                   list+="A";
                               }
                           }else if(temp.equals("B")){
                               if(B.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                  list+="B";
                               }
                           }else {
                               if(C.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                   list+="C";
                               }
                           }
                            counter++;
                        }while(counter<2);
                        System.out.print("Polynomial set in R: ");
                        print(add(list));
                        break;
                case 4:
                     int counter2=0;
                    String list2="";
                      do{
                          do{
                                System.out.println("Insert First Operand Variable name:: A, B or C");
                                temp=sc.nextLine();
                           }while(!temp.equals("A")&&!temp.equals("B")&&!temp.equals("C"));
                           if(temp.equals("A")){
                               if(A.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                   list2="A";
                               }
                           }else if(temp.equals("B")){
                               if(B.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                  list2="B";
                               }
                           }else {
                               if(C.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                   list2="C";
                               }
                           }
                           counter2++;
                            do{
                                System.out.println("Insert Second Operand Variable name:: A, B or C");
                                temp=sc.nextLine();
                            }while(!temp.equals("A")&&!temp.equals("B")&&!temp.equals("C"));
                           if(temp.equals("A")){
                               if(A.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                   list2+="A";
                               }
                           }else if(temp.equals("B")){
                               if(B.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                  list2+="B";
                               }
                           }else {
                               if(C.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                   list2+="C";
                               }
                           }
                            counter2++;
                        }while(counter2<2);
                        System.out.print("Polynomial set in R: ");
                        print(subtract(list2));
                        break;
                case 5:
                    R.clear();
                    int counter1=0;
                    String list1="";
                      do{
                          do{
                                System.out.println("Insert First Operand Variable name:: A, B or C");
                                temp=sc.nextLine();
                           }while(!temp.equals("A")&&!temp.equals("B")&&!temp.equals("C"));
                           if(temp.equals("A")){
                               if(A.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                   list1="A";
                               }
                           }else if(temp.equals("B")){
                               if(B.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                  list1="B";
                               }
                           }else {
                               if(C.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                   list1="C";
                               }
                           }
                           counter1++;
                            do{
                                System.out.println("Insert Second Operand Variable name:: A, B or C");
                                temp=sc.nextLine();
                            }while(!temp.equals("A")&&!temp.equals("B")&&!temp.equals("C"));
                           if(temp.equals("A")){
                               if(A.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                   list1+="A";
                               }
                           }else if(temp.equals("B")){
                               if(B.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                  list1+="B";
                               }
                           }else {
                               if(C.isEmpty()){
                                   System.out.println("Variable Not Set");
                                   continue;
                               }else{
                                   list1+="C";
                               }
                           }
                            counter1++;
                        }while(counter1<2);
                        System.out.print("Polynomial set in R: ");
                        print(multiply(list1));
                        break;
                case 6:
                    String t="";
                    do{

                                System.out.println("Insert Variable name: A, B, C or R");
                                t=sc.nextLine();
                      }while(!t.equals("A")&&!t.equals("B")&&!t.equals("C")&&!t.equals("R"));
                    String n1="";
                    Pattern pattern;
                    Matcher matcher;
                    do{
                                System.out.println("Enter Value :");
                                n1=sc.nextLine();
                                pattern=Pattern.compile("\\d");
                                matcher=pattern.matcher(n1);
                      }while(!matcher.find());

                    if(t.equals("A")){
                        evaluate(A,n1);
                    }else if(t.equals("B")){
                        evaluate(B,n1);
                    }else if(t.equals("C")){
                        evaluate(C,n1);
                    }else {
                        evaluate(R,n1);
                    }
                    break;
                case 7:
                      do{
                                System.out.println("Insert Variable name: A, B, C or R");
                                temp=sc.nextLine();
                      }while(!temp.equals("A")&&!temp.equals("B")&&!temp.equals("C")&&!temp.equals("R"));
                    if(temp.equals("A")){
                          A.clear();
                    }else if(temp.equals("B")){
                        B.clear();
                    }else if(temp.equals("C")){
                        C.clear();
                    }else{
                         R.clear();
                    }
                    break;
            }
        }
        private static void evaluate(MyLinkedListS<PolTerm> s,String n1){
            double x=Double.parseDouble(n1);
            double result=0;
            for(int i=1;i<=s.size();i++){
                result+=s.get(i).getCoeff()*Math.pow(x,s.get(i).getExp());
            }
            System.out.println("Result = "+result);
        }
        private static MyLinkedListS<PolTerm> subtract (String ls){
            char first=ls.charAt(0);
            char temp=ls.charAt(1);
            MyLinkedListS<PolTerm>negator=new MyLinkedListS<PolTerm>();
            if(temp=='A'){
                negator=negate(A);
            }else if(temp=='B'){
                negator=negate(B);
            }else{
                 negator=negate(C);
            }
            R.clear();
            if(first=='A'&&temp=='A'){
                R=add(A,negator,ls);
            }else if(first=='A'&&temp=='B'){
               R=add(A,negator,ls);
            }else if(first=='A'&&temp=='C'){
               R=add(A,negator,ls);
            }else if (first=='B'&&temp=='B'){
              R=add(B,negator,ls);
            }else if(first=='B'&&temp=='A'){
                R=add(B,negator,ls);
            }else if (first=='B'&&temp=='C'){
                R=add(B,negator,ls);
          }else if(first=='C'&&temp=='A'){
              R=add(C,negator,ls);
          }else if(first=='C'&&temp=='B'){
              R=add(C,negator,ls);
          }else if(first=='C'&&temp=='C'){
              R=add(C,negator,ls);
          }
            return R;
        }
        private static MyLinkedListS<PolTerm> add(MyLinkedListS<PolTerm> l,MyLinkedListS<PolTerm>l1,String ls){
            R=l.sublist(1, l.size());
            if(((ls.charAt(1))+"").equals("A")){
                R=R.concatenate(l1);
            }else if(((ls.charAt(1))+"").equals("B")){
                R=R.concatenate(l1);
            }else {
                R=R.concatenate(l1);
            }

            sortList(R);
            MyLinkedListS<PolTerm> list=new MyLinkedListS<PolTerm>();
            for(int i=1;i<=R.size();i++){
                int counter=i;
                double elements=R.getNode(counter).getElement().getCoeff();
                int ex=R.get(counter).getExp();
                while(counter<R.size()&&R.get(counter+1).getExp()==R.get(counter).getExp()){
                    elements+=R.get(counter+1).getCoeff();
                    counter++;
                }
                list.add(new PolTerm(elements,ex));
                i=counter;
            }
            R.clear();
            R=list.sublist(1, list.size());
            return R;
        }
        private static MyLinkedListS<PolTerm> negate(MyLinkedListS<PolTerm> p){
            MyLinkedListS<PolTerm> p1=new MyLinkedListS<PolTerm>();
            for(int i=1;i<=p.size();i++){
               p1.add(new PolTerm(-p.get(i).getCoeff(),p.get(i).getExp()));
            }
            return p1;
        }   
        private static MyLinkedListS<PolTerm> multiply(String ls){

          if(((ls.charAt(0))+"").equals("A")&&((ls.charAt(1))+"").equals("A")){
                R=multiplyP(A,A);
            }else if(((ls.charAt(0))+"").equals("A")&&((ls.charAt(1))+"").equals("B")||((ls.charAt(0))+"").equals("B")&&((ls.charAt(1))+"").equals("A")){
               R=multiplyP(A,B);
            }else if(((ls.charAt(0))+"").equals("A")&&((ls.charAt(1))+"").equals("C")||((ls.charAt(0))+"").equals("C")&&((ls.charAt(1))+"").equals("A")){
               R=multiplyP(A,C);
            }else if (((ls.charAt(0))+"").equals("B")&&((ls.charAt(1))+"").equals("B")){
              R=multiplyP(B,B);
            }else if(((ls.charAt(0))+"").equals("C")&&((ls.charAt(1))+"").equals("C")){
                R=multiplyP(C,C);
            }else if (((ls.charAt(0))+"").equals("B")&&((ls.charAt(1))+"").equals("C")||((ls.charAt(0))+"").equals("C")&&((ls.charAt(1))+"").equals("B")){
                R=multiplyP(B,C);
          }
            return R;
        }
        private static MyLinkedListS<PolTerm> multiplyP(MyLinkedListS<PolTerm>l1,MyLinkedListS<PolTerm>l2){
            MyLinkedListS<PolTerm> result=new MyLinkedListS<PolTerm>();

            for(int i=1;i<=l2.size();i++){
                for(int j=1;j<=l1.size();j++){
                    result.add(new PolTerm(l2.get(i).getCoeff()*l1.get(j).getCoeff(),l2.get(i).getExp()+l1.get(j).getExp()));
                }
            }
            sortList(result);
            MyLinkedListS<PolTerm> list1=new MyLinkedListS<PolTerm>();
            for(int i=1;i<=result.size();i++){
                int counter=i;
                double elements=result.get(counter).getCoeff();
                int ex=result.get(counter).getExp();
                while(counter<result.size()&&result.get(counter+1).getExp()==result.get(counter).getExp()){
                    elements+=result.getNode(counter+1).getElement().getCoeff();
                    counter++;
                }
                list1.add(new PolTerm(elements,ex));
                i=counter;
            }
            result.clear();
            result=list1.sublist(1, list1.size());
            return result;
        }
        private static MyLinkedListS<PolTerm> add(String ls){
             
            if(((ls.charAt(0))+"").equals("A")){
                R=A.sublist(1,A.size());
            }else if(((ls.charAt(0))+"").equals("B")){
                R=B.sublist(1,B.size());
            }else {
                R=C.sublist(1,C.size());
            }
            if(((ls.charAt(1))+"").equals("A")){
                R=R.concatenate(A);
            }else if(((ls.charAt(1))+"").equals("B")){
                R=R.concatenate(B);
            }else {
                R=R.concatenate(C);
            }
         
            sortList(R);
            MyLinkedListS<PolTerm> list=new MyLinkedListS<PolTerm>();
            for(int i=1;i<R.size();i++){
                int counter=i;
                double elements=R.getNode(counter).getElement().getCoeff();
                int ex=R.get(counter).getExp();
                while(counter<R.size()&&R.get(counter+1).getExp()==R.get(counter).getExp()){
                    elements+=R.get(counter+1).getCoeff();
                    counter++;
                }
                list.add(new PolTerm(elements,ex));
                i=counter;
            }
            R.clear();
            R=list.sublist(1, list.size());
            
            return R;
        }

        private static void printPol(String s){
            if(s.equals("A")){
                if(A.isEmpty()){
                    System.out.println("Empty Polynomial");
                }else{
                    System.out.print("Value in A: ");
                    print(A);
                }
            }else if(s.equals("B")){
                if(B.isEmpty()){
                    System.out.println("Empty Polynomial");
                }else{
                    System.out.print("Value in B: ");
                    print(B);
                }
            }else if(s.equals("C")){
                if(C.isEmpty()){
                    System.out.println("Empty Polynomial");
                }else{
                    System.out.print("Value in C: ");
                    print(C);
                }
            }else {
                if(R.isEmpty()){
                    System.out.println("Empty Polynomial");
                }else{
                    System.out.print("Value in R: ");
                    print(R);
                }
            }
        }
        private static void print(MyLinkedListS<PolTerm> l){
            MyLLIteratorS<PolTerm> it=l.getIterator();
            int counter=0;
            while(it.hasNext()){
                counter++;
                PolTerm pt=it.getNext();
                if(counter>1){
                    if(pt.getCoeff()>0){
                        System.out.print(" + ");
                    }else{
                        System.out.print(" - ");
                    }
                }
                if(counter==1){
                    if(pt.getCoeff()<0){
                        System.out.print("-");
                    }
                }
                System.out.print(Math.abs(pt.getCoeff()));
                if(pt.getExp()==1){
                    System.out.print("X");
                }else if(pt.getExp()!=0){
                    System.out.print("X^"+pt.getExp());
                }
            }
            System.out.println();
        }
        private static void insertPolynom(String name){
            Scanner sc=new Scanner(System.in);
            Matcher matcher;
            Pattern pattern;
            String s;
            
            //Asserting the format of the input.
            do{
            System.out.println("Insert the polynomial terms in the form: (coeff1, exponent1), (coeff2, exponent2),..");
                s=sc.nextLine();
                pattern=Pattern.compile("[(\\d,\\d)][(\\d, \\d)]");
                matcher=pattern.matcher(s);
            }while(!matcher.find());

            StringTokenizer st=new StringTokenizer(s);
            MyLinkedListS<PolTerm> elements=new MyLinkedListS<PolTerm>();

            //Keeping Terms entered in a linkedList then assgning it to the required polynomial.
            for(int i=0;st.hasMoreTokens();i++){
                String temp=st.nextToken(")");
                String temp1="";
                double coeff=0;
                int exp=0;
                int j=0;

                //Tracking The entered coefficient.
                for(j=temp.indexOf("(")+1;temp.charAt(j)!=',';j++){
                    temp1+=temp.charAt(j);
                }
                coeff=Double.parseDouble(temp1);
                temp1="";

                //Tracking the entered exponent.
                for(int k=j+1;k<temp.length();k++){
                    temp1+=temp.charAt(k);
                }
                exp=(int)Double.parseDouble(temp1);
                elements.add(new PolTerm(coeff,exp));
            }

      //      System.out.println(elements.getNode(1).getElement());

            //Copying elements to the required polynomial.
            if(name.equals("A")){
                A.clear();
                A=elements.sublist(1, elements.size());
                sortList(A);
                System.out.println("Polynomial A is set");
            }else if(name.equals("B")){
                B.clear();
                B=elements.sublist(1, elements.size());
                sortList(B);
                System.out.println("Polynomial B is set");
            }else {
                C.clear();
                C=elements.sublist(1, elements.size());
                sortList(C);
                System.out.println("Polynomial C is set");
            }
            elements.clear();

        }

        private static void sortList(MyLinkedListS<PolTerm> list){
            boolean isSorted = false;
            while(!isSorted)
            {
            isSorted = true; // this variable keeps track of whether to continue sorting or exit
            for (int i = 1; i <list.size(); i++){
            if (list.get(i).getExp() < list.get(i+1).getExp()){ // if current element is greater than the next{
                swap (list.getNode(i).getElement(),list.getNode(i+1).getElement()); // swap the two elements
                isSorted = false; // don't end the loop yet, we're not done
             }
            }
    }
 }
        private static void swap(PolTerm p1, PolTerm p2) {
            PolTerm temp= new PolTerm(p2.getCoeff(),p2.getExp());
            p2.setCoeff(p1.getCoeff());
            p2.setExp(p1.getExp());
            p1.setCoeff(temp.getCoeff());
            p1.setExp(temp.getExp());
        }
        
        private static void getInstructions() {
		System.out.println("Please choose an action\n"
				+ "-----------------------");
		System.out.println("1- Set a polynomial variable");
		System.out.println("2- Print the value of a polynomial variable");
		System.out.println("3- Add two polynomials");
		System.out.println("4- Subtract two polynomials");
		System.out.println("5- Multiply two polynomials");
		System.out.println("6- Evaluate a polynomial at some point");
		System.out.println("7- Clear a polynomial variable");
	}

    	public static void main(String[] args) {
            
            while(true) request(takeAction());
            

//                System.out.printf("I found the text \"%s\" starting at " +
//                   "index %d and ending at index %d.\n",
//                    matcher.group(), matcher.start(), matcher.end());

        }


}
